/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 * Licensed under the Apache License, Version 2.0(the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "comstack_types.h"
#include "cannm.h"
#include "cannm_internal.h"
#if (CONFIG_MODULE_NM == 1)
#include "nm.h"
#endif
#include "SchM_CanNm.h"
#if (CONFIG_MODULE_CANIF == 1)
#include "canif.h"
#endif

#include "vcos_log.h"
#include "cannm_vcos_log.h"
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON) && (CONFIG_MODULE_PDUR == 1)
#include "pdur_cannm.h"
#endif
#if (CANNM_PN_FEATURE_ENABLED == STD_ON) && (CONFIG_MODULE_CANSM == 1)
# include "cansm.h"
#endif
#include <string.h>
#if (CANNM_DEV_ERROR_DETECT == STD_ON) && defined(VCOS_MODULE_CONFIG_DET) && (VCOS_MODULE_CONFIG_DET == 1)
#include "Det.h"
#endif

#include "Compiler.h"

#define CANNM_START_SEC_CODE
#include "cannm_memmap.h"

FUNC(void, CANNM_CODE) cannm_get_chnl_run_time_data(const network_handle_type channel_id,
	uint16 *left_msg_cyc_tm, uint16 *left_tmot_tm)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NO_INIT);
		return;
	}
	if (channel_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	if ((NULL == left_msg_cyc_tm) || (NULL == left_tmot_tm)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NULL_POINTER);
		return;
	}
	const cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_id];

	*left_msg_cyc_tm =  channel_internal->left_msg_cyc_tm;
	*left_tmot_tm = channel_internal->left_tmot_tm;
}

FUNC(void, CANNM_CODE) cannm_init(const cannm_cate_cfg *const cannm_config)
{
	if (NULL == cannm_config) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_INIT_CANNM_E_NULL_POINTER);
		return;
	}
	cannm_config_ptr = cannm_config;

	for (uint8 channel = 0u; channel < CANNM_CHANNEL_COUNT; channel++) {
		const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel];
		cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel];
		(void)memset(channel_internal, 0x00u, sizeof(cannm_op_chnl_cate));
		channel_internal->support_comm = (boolean)TRUE;

		if (channel_conf->pos_nid != CANNM_PDU_OFF) {
			channel_internal->pdu_tx[channel_conf->pos_nid] = channel_conf->nd_id;
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
			channel_internal->spts_tx_msg[channel_conf->pos_nid] = channel_conf->nd_id;
#endif
		}

		if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
			for (uint8_t i = 2; i < 8; i++) {
				channel_internal->pdu_tx[i] = CANNM_INVALID_VALUE;
			}
		}
	}

	cannm_internal.init_status = CANNM_STATUS_INIT;
}

FUNC(void, CANNM_CODE) cannm_de_init(void)
{
	boolean cannm_wake_flag = (boolean)FALSE;

	for (uint8 channel = 0u; channel < CANNM_CHANNEL_COUNT; channel++) {
		const cannm_op_chnl_cate *channel_internal =
		(const cannm_op_chnl_cate *)&cannm_internal.nm_tunnel[channel];
		if (channel_internal->mode != NM_MODE_BUS_SLEEP) {
			cannm_wake_flag = (boolean)TRUE;
			break;
		}
	}
	if ((boolean)TRUE == cannm_wake_flag) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_DEINIT_CANNM_E_NOT_IN_BUS_SLEEP);
	}
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_pas_stup(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_PASSIVESTARTUP_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_PASSIVESTARTUP_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}

	Std_ReturnType status = E_OK;
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];

	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	switch (channel_internal->mode) {
		case NM_MODE_BUS_SLEEP:
			cannm_bs_to_rpt_msg_proc(channel_conf, channel_internal, (boolean)FALSE);
			status = E_OK;
			break;
		case NM_MODE_PREPARE_BUS_SLEEP:
			cannm_pbs_to_rpt_msg_proc(channel_conf, channel_internal, (boolean)FALSE);
			status = E_OK;
			break;
		default:
			status = E_NOT_OK;
			break;
	}

#if (CANNM_PN_FEATURE_ENABLED == STD_ON)
	if (channel_conf->pn_support) {
		cannm_set_pni_cbv(channel_conf,channel_internal);
	}
#endif
	return status;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_req_net(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_NETWORKREQUEST_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_NETWORKREQUEST_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	channel_internal->requested = (boolean)TRUE;
	switch (channel_internal->mode) {
		case NM_MODE_BUS_SLEEP:
			cannm_bs_to_rpt_msg_proc(channel_conf, channel_internal, (boolean)TRUE);
#if (CANNM_ACTIVE_WUP_BIT_FEATURE_ENABLED == STD_ON)
			cannm_set_active_wk_cbv(channel_conf, channel_internal);
#endif
			break;
		case NM_MODE_PREPARE_BUS_SLEEP:
			cannm_pbs_to_rpt_msg_proc(channel_conf, channel_internal, (boolean)TRUE);
#if (CANNM_ACTIVE_WUP_BIT_FEATURE_ENABLED == STD_ON)
			cannm_set_active_wk_cbv(channel_conf, channel_internal);
#endif
			break;
		case NM_MODE_NETWORK:
			switch (channel_internal->state) {
#if (STD_OFF == CANNM_PN_HANDLE_MULTIPLE_NETWORK_REQUESTS)
				case NM_STATE_READY_SLEEP:
					cannm_rdy_slp_to_nor_opr_proc(channel_conf, channel_internal);
					break;
#else
				case NM_STATE_READY_SLEEP:
					cannm_rdy_slp_to_rpt_msg_proc(channel_conf, channel_internal);
					break;
				case NM_STATE_NORMAL_OPERATION:
					cannm_nor_opr_to_rpt_msg_proc(channel_conf, channel_internal);
					break;
				case NM_STATE_REPEAT_MESSAGE:
					cannm_rpt_msg_to_rpt_msg_proc(channel_conf, channel_internal);
					break;
#endif
				default:
					break;
			}
			break;
		default:
			break;
	}

#if (CANNM_PN_FEATURE_ENABLED == STD_ON)
	if (channel_conf->pn_support) {
		cannm_set_pni_cbv(channel_conf, channel_internal);
	}
#endif
	return E_OK;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_rel_net(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_NETWORKRELEASE_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_NETWORKRELEASE_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}

	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	if (FALSE == channel_internal->support_comm) {
		return E_NOT_OK;
	}
	channel_internal->requested = (boolean)FALSE;
	if (NM_MODE_NETWORK == channel_internal->mode && NM_STATE_NORMAL_OPERATION == channel_internal->state) {
		cannm_nor_opr_to_rdy_slp_proc(channel_conf, channel_internal);
	}
	return E_OK;
}

#if (CANNM_COM_CONTROL_ENABLED == STD_ON)
FUNC(Std_ReturnType, CANNM_CODE) cannm_disable_comm(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_DISABLECOMMUNICATION_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}

#if (CANNM_PASSIVE_MODE_ENABLED == STD_ON)
	return E_NOT_OK;
#endif

	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_DISABLECOMMUNICATION_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	if (channel_internal->mode != NM_MODE_NETWORK) {
		return E_NOT_OK;
	}

	channel_internal->support_comm = (boolean)FALSE;

	return E_OK;
}
#endif

#if (CANNM_COM_CONTROL_ENABLED == STD_ON)
FUNC(Std_ReturnType, CANNM_CODE) cannm_enable_comm(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_ENABLECOMMUNICATION_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}

#if (CANNM_PASSIVE_MODE_ENABLED == STD_ON)
	return E_NOT_OK;
#endif

	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_ENABLECOMMUNICATION_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];

	if (channel_internal->mode != NM_MODE_NETWORK) {
		return E_NOT_OK;
	}

	if (channel_internal->support_comm) {
		return E_NOT_OK;
	}

	channel_internal->left_msg_cyc_tm = channel_conf->msg_cys_ofst_tm +	channel_conf->m_func_pid;
	channel_internal->left_tmot_tm = channel_conf->tm_out + channel_conf->m_func_pid;
	channel_internal->support_comm = (boolean)TRUE;

	return E_OK;
}
#endif

#if (CANNM_PASSIVE_MODE_ENABLED == STD_OFF) && (CANNM_USER_DATA_ENABLED == STD_ON) && \
(CANNM_COM_USER_DATA_SUPPORT == STD_OFF)
FUNC(Std_ReturnType, CANNM_CODE) cannm_set_ur_data(const network_handle_type nm_id,
const uint8 *const nm_user_data_ptr)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_SETUSERDATA_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_SETUSERDATA_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	if (NULL == nm_user_data_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_SETUSERDATA_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	Std_ReturnType ret_val = E_NOT_OK;
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	if (!channel_internal->is_pdu_set) {
		channel_internal->is_pdu_set = (boolean)TRUE;
		uint8 *dest_ur_data = cannm_ur_data_ptr_get(channel_conf, channel_internal->pdu_tx);
		PduLengthType user_data_length = cannm_ur_data_len_get(channel_conf);
		(void)memcpy(dest_ur_data, nm_user_data_ptr, (size_t)user_data_length);
		channel_internal->is_pdu_set = (boolean)FALSE;
		ret_val = E_OK;
	}

	return ret_val;
}
#endif

#if (CANNM_USER_DATA_ENABLED == STD_ON)
FUNC(Std_ReturnType, CANNM_CODE) cannm_get_ur_data(const network_handle_type nm_id, uint8 *const nm_user_data_ptr)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETUSERDATA_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETUSERDATA_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	if (NULL == nm_user_data_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETUSERDATA_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
	const uint8 *source_user_data = cannm_ur_data_ptr_get(channel_conf, channel_internal->pdu_rx);
	PduLengthType user_data_length = cannm_ur_data_len_get(channel_conf);

	if (0u < user_data_length) {
		(void)memcpy(nm_user_data_ptr, source_user_data, (size_t)user_data_length);
	}

	return E_OK;
}
#endif

FUNC(Std_ReturnType, CANNM_CODE) cannm_get_nd_id(const network_handle_type nm_id,
uint8 *const nm_node_id_ptr)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETNODEIDENTIFIER_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETNODEIDENTIFIER_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	if (NULL == nm_node_id_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETNODEIDENTIFIER_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	const cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
	Std_ReturnType status = E_NOT_OK;

	if (CANNM_PDU_OFF != channel_conf->pos_nid) {
		*nm_node_id_ptr = channel_internal->pdu_rx[channel_conf->pos_nid];
		status = E_OK;
	}
	return status;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_get_local_nd_id(const network_handle_type nm_id,
	uint8 *const nm_node_id_ptr)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETLOCALNODEIDENTIFIER_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETLOCALNODEIDENTIFIER_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	if (NULL == nm_node_id_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETLOCALNODEIDENTIFIER_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	*nm_node_id_ptr = channel_conf->nd_id;

	return E_OK;
}

#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
FUNC(Std_ReturnType, CANNM_CODE) cannm_req_rpt_msg(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_REPEATMESSAGEREQUEST_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_REPEATMESSAGEREQUEST_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
	Std_ReturnType status = E_NOT_OK;

	if ((NM_STATE_REPEAT_MESSAGE == channel_internal->state) ||
	(NM_MODE_PREPARE_BUS_SLEEP == channel_internal->mode) ||
	(NM_MODE_BUS_SLEEP == channel_internal->mode)) {
		return status;
	}
	if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
		switch (channel_internal->state) {
			case NM_STATE_READY_SLEEP:
				channel_internal->pdu_tx[channel_conf->pos_cbv] |= CANNM_CBV_REPEAT_MESSAGE_REQUEST;
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
				channel_internal->spts_tx_msg[channel_conf->pos_cbv] |=
				CANNM_CBV_REPEAT_MESSAGE_REQUEST;
#endif
				cannm_rdy_slp_to_rpt_msg_proc(channel_conf, channel_internal);
				status = E_OK;
				break;
			case NM_STATE_NORMAL_OPERATION:
				channel_internal->pdu_tx[channel_conf->pos_cbv] |=  CANNM_CBV_REPEAT_MESSAGE_REQUEST;
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
				channel_internal->spts_tx_msg[channel_conf->pos_cbv] |=
				CANNM_CBV_REPEAT_MESSAGE_REQUEST;
#endif
				cannm_nor_opr_to_rpt_msg_proc(channel_conf, channel_internal);
				status = E_OK;
				break;
			default:
				break;
		}
	}
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON) && (CANNM_REPEAT_MSG_IND_ENABLED == STD_ON)
	nm_rpt_msg_ind(CANNM_CHANNEL_COUNT);
#endif
	return status;
}
#endif

FUNC(Std_ReturnType, CANNM_CODE) cannm_get_msg_data(const network_handle_type nm_id, uint8 *const nm_pdu_data_ptr)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETPDUDATA_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETPDUDATA_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	if (NULL == nm_pdu_data_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETPDUDATA_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	const cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	(void)memcpy(nm_pdu_data_ptr, channel_internal->pdu_rx, (size_t)channel_conf->msg_size);

	return E_OK;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_get_state(const network_handle_type nm_id,
	nm_state_type *const nm_st, nm_mode_type *const nm_md)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NO_INIT);
		return E_NOT_OK;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}
	if (NULL == nm_st) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if (NULL == nm_md)
	{
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
	*nm_st = channel_internal->state;
	*nm_md = channel_internal->mode;

	return E_OK;
}

FUNC(void, CANNM_CODE) cannm_tx_confirmation(PduIdType cannm_tx_pdu_id, Std_ReturnType result)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TXCONFIRMATION_CANNM_E_NO_INIT);
		return;
	}
	if (cannm_tx_pdu_id >= NM_CHANNEL_COUNT) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TXCONFIRMATION_CANNM_E_INVALID_PDUID);
		return;
	}
	(void)Os_AtomicInc(&cannm_msg_cnt.txconf_ok_msg_cnt);
	(void)result;
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[cannm_tx_pdu_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
#if (CONFIG_MODULE_PDUR == 1)
	pdur_cannm_tx_confirmation(channel_conf->ur_data_tx_pid, result);
#endif

	if (CANNM_SPONTANEOUS_TRANSMISSION == channel_internal->tx_sts) {
		channel_internal->tx_sts = CANNM_NO_TRANSMISSION;
	} else
#endif
	{
		switch (channel_internal->mode) {
			case NM_MODE_NETWORK:
				cannm_net_mode_to_net_mode_proc(channel_conf, channel_internal);
				break;
			default:
				break;
		}
	}

	channel_internal->left_msg_tmot_tm = 0u;
}

#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
FUNC(void, CANNM_CODE) cannm_net_mode_rx_ind_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal, boolean repeat_message_bit_indication)
{
	if (NULL == channel_conf) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_NETWORKMODE_RXINDICATION_CANNM_E_NULL_POINTER);
		return;
	}
	if (NULL == channel_internal) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_NETWORKMODE_RXINDICATION_CANNM_E_NULL_POINTER);
		return;
	}
	if (TRUE == repeat_message_bit_indication) {
		switch (channel_internal->state) {
			case NM_STATE_READY_SLEEP:
				cannm_rdy_slp_to_rpt_msg_proc(channel_conf, channel_internal);
				break;
			case NM_STATE_NORMAL_OPERATION:
				cannm_nor_opr_to_rpt_msg_proc(channel_conf, channel_internal);
				break;
			default:
				break;
		}
	}
	return;
}
#endif

FUNC(void, CANNM_CODE) cannm_rx_indication(PduIdType cannm_rx_pdu_id, const PduInfoType *pdu_info_ptr)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RXINDICATION_CANNM_E_NO_INIT);
		return;
	}
	if (NULL == pdu_info_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RXINDICATION_CANNM_E_NULL_POINTER);
		return;
	}
	if (NULL == pdu_info_ptr->SduDataPtr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RXINDICATION_CANNM_E_NULL_POINTER);
		return;
	}
	if (cannm_rx_pdu_id >= NM_CHANNEL_COUNT) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RXINDICATION_CANNM_E_INVALID_PDUID);
		return;
	}
	(void)Os_AtomicInc(&cannm_msg_cnt.rx_ok_msg_cnt);

	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[cannm_rx_pdu_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	(void)memcpy(channel_internal->pdu_rx, pdu_info_ptr->SduDataPtr, (size_t)channel_conf->msg_size);
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
	boolean repeat_message_bit_indication = (boolean)FALSE;
#endif
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON) || (CANNM_PN_FEATURE_ENABLED == STD_ON)
	if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
		uint8 cbv = channel_internal->pdu_rx[channel_conf->pos_cbv];
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
		if ((cbv & CANNM_CBV_REPEAT_MESSAGE_REQUEST) != 0u) {
			repeat_message_bit_indication = (boolean)TRUE;
		}
#endif
#if (CANNM_PN_FEATURE_ENABLED == STD_ON)
		boolean pni = FALSE;

		if ((cbv & CANNM_CBV_PNI) != 0U) {
			pni = (boolean)TRUE;
		}
		if (E_NOT_OK == cannm_rx_proc(channel_conf,channel_internal, pni)) {
			return;
		}
#endif
	}
#endif
	switch (channel_internal->mode) {
		case NM_MODE_BUS_SLEEP:
			cannm_bs_to_bs_proc(channel_conf, channel_internal);
			break;
		case NM_MODE_PREPARE_BUS_SLEEP:
			cannm_pbs_to_rpt_msg_proc(channel_conf, channel_internal,(boolean)FALSE);
			break;
		case NM_MODE_NETWORK:
			cannm_net_mode_to_net_mode_proc(channel_conf, channel_internal);
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
			cannm_net_mode_rx_ind_proc(channel_conf, channel_internal, repeat_message_bit_indication);
#endif
			break;
		default:
			break;
	}

#if (CANnm_pdu_rx_ind_ENABLED == STD_ON)
	nm_rx_pdu_ind((network_handle_type)cannm_rx_pdu_id, pdu_info_ptr);
#endif

	return;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_transmit(PduIdType ur_data_tx_pid, const PduInfoType *pdu_info_ptr)
{
	if (ur_data_tx_pid >= NM_CHANNEL_COUNT) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRANSMIT_CANNM_E_INVALID_PDUID);
		return E_NOT_OK;
	}
	if (NULL == pdu_info_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRANSMIT_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if (NULL == pdu_info_ptr->SduDataPtr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRANSMIT_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	Std_ReturnType ret_val = E_NOT_OK;
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
	boolean found = (boolean)FALSE;
	uint8 chnl_idx = 0u;

	for (chnl_idx = 0u; chnl_idx < CANNM_CHANNEL_COUNT; chnl_idx++) {
		if (ur_data_tx_pid == cannm_config_ptr->nm_tunnel[chnl_idx].ur_data_tx_pid) {
			found = (boolean)TRUE;
			break;
		}
	}
	if (FALSE == found) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRANSMIT_CANNM_E_INVALID_PDUID);
		return E_NOT_OK;
	}
	if ((chnl_idx >= cannm_config_ptr->chnl_num_len) ||
	(cannm_config_ptr->chnl_num[chnl_idx] == CANNM_INVALID_VALUE)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRANSMIT_CANNM_E_INVALID_CHANNEL);
		return E_NOT_OK;
	}

	if (chnl_idx < CANNM_CHANNEL_COUNT) {
		const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[chnl_idx];
		cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[chnl_idx];

		if (((NM_STATE_REPEAT_MESSAGE == channel_internal->state) || (NM_STATE_NORMAL_OPERATION ==
		channel_internal->state)) && (channel_internal->support_comm)) {
			if (CANNM_NO_TRANSMISSION == channel_internal->tx_sts) {
				uint8 *dest_ur_data = cannm_ur_data_ptr_get(channel_conf,
					channel_internal->spts_tx_msg);
				PduLengthType user_data_length = cannm_ur_data_len_get(channel_conf);

				channel_internal->tx_sts = CANNM_SPONTANEOUS_TRANSMISSION;
				if (0u < user_data_length) {
					(void)memcpy(dest_ur_data, pdu_info_ptr->SduDataPtr, (size_t)user_data_length);
				}

				PduInfoType pdu =
				{
					.SduDataPtr = dest_ur_data,
					.SduLength = channel_conf->msg_size,
				};
				ret_val = canif_transmit(channel_conf->canif_pid, &pdu);

				if (ret_val != E_OK) {
					channel_internal->tx_sts = CANNM_NO_TRANSMISSION;
				}
			} else {
				/* Do nothing */
			}
		}
	}

#endif
	return ret_val;
}

FUNC(void, CANNM_CODE) cannm_state_rpt_msg_handling(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	cannm_rpt_msg_time_proc(channel_conf, channel_internal);
#if (CANNM_PASSIVE_MODE_ENABLED != STD_ON)
	cannm_tx_tmot_troc(channel_conf, channel_internal);
#endif
	if (channel_internal->support_comm) {
		cannm_tmot_time_proc(channel_conf, channel_internal);
#if (CANNM_PASSIVE_MODE_ENABLED != STD_ON)
		if ((NM_STATE_REPEAT_MESSAGE == channel_internal->state) || (NM_STATE_NORMAL_OPERATION ==
			channel_internal->state)) {
			cannm_msg_cyc_time_proc(channel_conf, channel_internal);
		}
#endif
	}
}

FUNC(void, CANNM_CODE) cannm_state_nor_opr_handling(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	#if (CANNM_PASSIVE_MODE_ENABLED != STD_ON)
	cannm_tx_tmot_troc(channel_conf, channel_internal);
	#endif
	if (channel_internal->support_comm) {
		cannm_tmot_time_proc(channel_conf, channel_internal);
#if (CANNM_PASSIVE_MODE_ENABLED != STD_ON)
		if ((NM_STATE_REPEAT_MESSAGE == channel_internal->state) ||
			(NM_STATE_NORMAL_OPERATION == channel_internal->state)) {
			cannm_msg_cyc_time_proc(channel_conf, channel_internal);
		}
#endif
	}
}

FUNC(void, CANNM_CODE) cannm_state_rdy_slp_handling(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
#if (CANNM_PASSIVE_MODE_ENABLED != STD_ON)
	cannm_tx_tmot_troc(channel_conf, channel_internal);
#endif
	if (channel_internal->support_comm) {
		cannm_tmot_time_proc(channel_conf, channel_internal);
	}
}

FUNC(void, CANNM_CODE) cannm_mode_net_handling(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	switch (channel_internal->state) {
		case NM_STATE_REPEAT_MESSAGE:
			cannm_state_rpt_msg_handling(channel_conf, channel_internal);
			break;
		case NM_STATE_NORMAL_OPERATION:
			cannm_state_nor_opr_handling(channel_conf, channel_internal);
			break;
		case NM_STATE_READY_SLEEP:
			cannm_state_rdy_slp_handling(channel_conf, channel_internal);
			break;
		default:
			break;
	}
}

FUNC(void, CANNM_CODE) cannm_m_func_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}

	switch (channel_internal->mode) {
		case NM_MODE_NETWORK:
			cannm_mode_net_handling(channel_conf, channel_internal);
			break;

		case NM_MODE_PREPARE_BUS_SLEEP:
			cannm_mode_pbs_handling(channel_conf, channel_internal);
			break;
		default:
			break;
	}
}

FUNC(void, CANNM_CODE) cannm_mtpl_m_func_proc(void)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NO_INIT);
		return;
	}
#if (CANNM_MULTICORE_ENABLED == STD_ON)
	cannm_core_id_type core_id = (cannm_core_id_type)GetCoreID();
#else
	cannm_core_id_type core_id = CANNM_SINGLECORE_COREID;
#endif
	const cannm_core_channel_id_mapping_type *tunnel_trans = cannm_channel_id_mapping_by_core_id(core_id);

	if (NULL == tunnel_trans) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (NULL == tunnel_trans->net_tbl_addr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	cannm_channel_num_type channel_num = tunnel_trans->network_table_len;

	for (uint8 channel = 0u; channel < channel_num; channel++) {
		const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[tunnel_trans->net_tbl_addr[channel]];
		cannm_op_chnl_cate *channel_internal =
			&cannm_internal.nm_tunnel[tunnel_trans->net_tbl_addr[channel]];
		cannm_m_func_proc(channel_conf, channel_internal);
	}
}

FUNC(void, CANNM_CODE) cannm_confirm_pn_availability(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_CONFIRMPNAVAILABILITY_CANNM_E_NO_INIT);
		return;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_CONFIRMPNAVAILABILITY_CANNM_E_INVALID_CHANNEL);
		return;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];

	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];

	channel_internal->filter_pdu = channel_conf->pn_support;
}

FUNC(void, CANNM_CODE) cannm_tmot_time_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (channel_conf->m_func_pid >= channel_internal->left_tmot_tm) {
		channel_internal->left_tmot_tm = 0u;
		switch (channel_internal->state) {
			case NM_STATE_REPEAT_MESSAGE:
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
				channel_internal->tx_sts = CANNM_NO_TRANSMISSION;
#endif
				cannm_rpt_msg_to_rpt_msg_proc(channel_conf, channel_internal);
				break;
			case NM_STATE_NORMAL_OPERATION:
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
				channel_internal->tx_sts = CANNM_NO_TRANSMISSION;
#endif
				cannm_nor_opr_to_nor_opr_proc(channel_conf, channel_internal);
				break;
			case NM_STATE_READY_SLEEP:
				cannm_rdy_slp_to_pbs_proc(channel_conf, channel_internal);
				break;
			default:
				break;
		}
	} else {
		channel_internal->left_tmot_tm -= channel_conf->m_func_pid;
	}
}

FUNC(void, CANNM_CODE) cannm_rpt_msg_time_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->left_rpt_msg_tm = (channel_conf->m_func_pid >= channel_internal->left_rpt_msg_tm)
	? 0u : (channel_internal->left_rpt_msg_tm - channel_conf->m_func_pid);

	if (0u == channel_internal->left_rpt_msg_tm) {
		(channel_internal->requested)
			? cannm_rpt_msg_to_nor_opr_proc(channel_conf, channel_internal)
			: cannm_rpt_msg_to_rdy_slp_proc(channel_conf, channel_internal);
	}
}

FUNC(void, CANNM_CODE) cannm_mode_pbs_handling(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->left_wait_bs_tm = (channel_conf->m_func_pid >= channel_internal->left_wait_bs_tm)
	? 0u : (channel_internal->left_wait_bs_tm - channel_conf->m_func_pid);

	if ((0u == channel_internal->left_wait_bs_tm) && (NM_MODE_PREPARE_BUS_SLEEP == channel_internal->mode)) {
		cannm_pbs_to_bs_proc(channel_conf, channel_internal);
	}
}

FUNC(void, CANNM_CODE) cannm_tx_tmot_troc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (0U != channel_internal->left_msg_tmot_tm) {
		if (channel_conf->m_func_pid >= channel_internal->left_msg_tmot_tm) {
			nm_tx_tmot_excpt_pro(channel_conf->id_net);
#if (CANNM_PN_FEATURE_ENABLED == STD_ON) && (CONFIG_MODULE_CANSM == 1)
			if ((boolean)TRUE == channel_conf->pn_support) {
				(void)cansm_tx_timeout_exception(channel_conf->id_net);
			}
#endif
			channel_internal->left_msg_tmot_tm = 0u;
		} else {
			channel_internal->left_msg_tmot_tm -= channel_conf->m_func_pid;
		}
	}
}

FUNC(void, CANNM_CODE) cannm_msg_cyc_time_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (channel_conf->m_func_pid >= channel_internal->left_msg_cyc_tm) {
		if ((boolean)TRUE == channel_internal->imdt_en_mode) {
			channel_internal->left_msg_cyc_tm = channel_conf->imdt_nm_cyc_tm;
		} else {
			channel_internal->left_msg_cyc_tm = channel_conf->msg_cyc_tm;
		}
#if (CANNM_BUS_LOAD_REDUCTION_ENABLED == STD_ON) && (CANNM_BUS_LOAD_REDUCTION_ACTIVE == STD_ON)
		if (NM_STATE_NORMAL_OPERATION == channel_internal->state) {
			channel_internal->left_msg_cyc_tm = channel_conf->msg_rdc_tm;
		}
#endif
		cannm_tx_msg(channel_conf, channel_internal);
	} else {
		channel_internal->left_msg_cyc_tm -= channel_conf->m_func_pid;
	}
}

FUNC(void, CANNM_CODE) cannm_tx_msg(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	Std_ReturnType transmit_status = E_NOT_OK;
	PduInfoType pdu;
	(void)memset(&pdu, 0, sizeof(pdu));
	pdu.SduDataPtr = channel_internal->pdu_tx;
	pdu.SduLength = channel_conf->msg_size;

	if (FALSE == channel_internal->support_comm) {
		return;
	}

#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
	if (CANNM_NO_TRANSMISSION == channel_internal->tx_sts) {
		SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
		channel_internal->tx_sts = CANNM_ONGOING_TRANSMISSION;
		SchM_Exit_CANNM_EXCLUSIVE_AREA_0();

#if (CONFIG_MODULE_PDUR == 1)
		PduInfoType user_data;

		user_data.SduDataPtr = cannm_ur_data_ptr_get(channel_conf, channel_internal->pdu_tx);
		user_data.SduLength = cannm_ur_data_len_get(channel_conf);
		(void)pdur_cannm_trigger_transmit(channel_conf->ur_data_tx_pid, &user_data);
#endif
#elif (CANNM_USER_DATA_ENABLED == STD_ON)
	if (FALSE == channel_internal->is_pdu_set) {
		SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
		channel_internal->is_pdu_set = (boolean)TRUE;
		SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#endif
		channel_internal->left_msg_tmot_tm = channel_conf->msg_tmot_tm;

#if (CANNM_CALLOUT_CONFIG == STD_ON)
		if (E_OK == CANNM_CALLBACK_FUNCTION()) {
			transmit_status = canif_transmit(channel_conf->canif_pid, &pdu);
		}
#else
		transmit_status = canif_transmit(channel_conf->canif_pid, &pdu);
#endif

		if (transmit_status != E_OK) {
			(void)Os_AtomicInc(&cannm_msg_cnt.tx_not_ok_msg_cnt);
		} else {
			(void)Os_AtomicInc(&cannm_msg_cnt.tx_ok_msg_cnt);
		}
#if (CANNM_RETRY_FIRST_MESSAGE_REQUEST == STD_ON)
		network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[channel_conf->id_net];

		cannm_retry_first_msg_flg[cannm_net_id] = cannm_get_retry_first_msg_flg(cannm_net_id);
		if ((boolean)TRUE == cannm_retry_first_msg_flg[cannm_net_id]) {
			if (E_OK == transmit_status) {
				cannm_retry_first_msg_flg[cannm_net_id] = (boolean)FALSE;
				if (canif_transmit_flag == 0u) {
					canif_transmit_flag = 1u;
					canif_first_nm_msg_id = channel_conf->canif_pid;
				}
			} else {
				channel_internal->left_msg_cyc_tm = 0u;
			}
		}
#endif
		if ((boolean)TRUE == channel_internal->imdt_en_mode) {
			channel_internal->imdt_tx_sd++;
#if (CANNM_RETRY_FIRST_MESSAGE_REQUEST == STD_ON)
			if ((boolean)TRUE == cannm_retry_first_msg_flg[cannm_net_id])
				channel_internal->imdt_tx_sd--;
#endif
			if (channel_internal->imdt_tx_sd == channel_conf->imdt_tx) {
				channel_internal->imdt_en_mode = (boolean)FALSE;
				channel_internal->left_msg_cyc_tm = (0U != channel_conf->msg_cys_ofst_tm)
				? channel_conf->msg_cys_ofst_tm : channel_conf->msg_cyc_tm;
			}
		}
#if (CANNM_BUS_LOAD_REDUCTION_ENABLED == STD_ON) && (CANNM_BUS_LOAD_REDUCTION_ACTIVE == STD_ON)
		if (NM_STATE_NORMAL_OPERATION == channel_internal->state) {
			channel_internal->left_msg_cyc_tm = channel_conf->msg_rdc_tm;
		}
#endif

#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
		channel_internal->tx_sts = CANNM_NO_TRANSMISSION;
	}
#elif (CANNM_USER_DATA_ENABLED == STD_ON)
		channel_internal->is_pdu_set = (boolean)FALSE;
	}
#endif
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_trigger_transmit(PduIdType tx_pdu_id, PduInfoType *pdu_info_ptr)
{
	if (NULL == pdu_info_ptr) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRIGGERTRANSMIT_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if (tx_pdu_id >= NM_CHANNEL_COUNT) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_TRIGGERTRANSMIT_CANNM_E_INVALID_PDUID);
		return E_NOT_OK;
	}
	Std_ReturnType ret_val = E_NOT_OK;
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[tx_pdu_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

#if ( CANNM_COM_USER_DATA_SUPPORT == STD_ON )
	pdu_info_ptr->SduDataPtr = cannm_ur_data_ptr_get(channel_conf, channel_internal->pdu_tx);
	pdu_info_ptr->SduLength = cannm_ur_data_len_get(channel_conf);
#if (CONFIG_MODULE_PDUR == 1)
	(void)pdur_cannm_trigger_transmit(channel_conf->ur_data_tx_pid, pdu_info_ptr);
#endif
#endif

	pdu_info_ptr->SduDataPtr = channel_internal->pdu_tx;
	pdu_info_ptr->SduLength = channel_conf->msg_size;

	ret_val = canif_transmit(tx_pdu_id, pdu_info_ptr);

	if (ret_val != E_OK) {
		(void)Os_AtomicInc(&cannm_msg_cnt.tt_tx_not_ok_msg_cnt);
	} else {
		(void)Os_AtomicInc(&cannm_msg_cnt.tt_tx_ok_msg_cnt);
	}

	return ret_val;
}

FUNC(PduLengthType, CANNM_CODE) cannm_ur_data_ofst_get(const cannm_chnl_cate *channel_conf)
{
	if (NULL == channel_conf) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return 0u;
	}
	PduLengthType user_data_pos = 0u;

	user_data_pos += (CANNM_PDU_OFF == channel_conf->pos_nid) ? 0U : 1U;
	user_data_pos += (CANNM_PDU_OFF == channel_conf->pos_cbv) ? 0U : 1U;
	return user_data_pos;
}

FUNC_P2VAR(uint8, AUTOMATIC, CANNM_CODE) cannm_ur_data_ptr_get(const cannm_chnl_cate *channel_conf,
	uint8 *MessageSduPtr)
{
	PduLengthType user_data_offset = cannm_ur_data_ofst_get(channel_conf);

	return &MessageSduPtr[user_data_offset];
}

FUNC(PduLengthType, CANNM_CODE) cannm_ur_data_len_get(const cannm_chnl_cate *channel_conf)
{
	if (NULL == channel_conf) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return 0u;
	}
	PduLengthType user_data_offset = cannm_ur_data_ofst_get(channel_conf);

	if (user_data_offset > channel_conf->msg_size) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return 0u;
	}
	return channel_conf->msg_size - user_data_offset;
}

#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
FUNC(void, CANNM_CODE) cannm_clr_rpt_msg_req_cbv(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
		channel_internal->pdu_tx[channel_conf->pos_cbv] &= (uint8)(~(CANNM_CBV_REPEAT_MESSAGE_REQUEST));
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
		channel_internal->spts_tx_msg[channel_conf->pos_cbv] &= ~(CANNM_CBV_REPEAT_MESSAGE_REQUEST);
#endif
	}
}
#endif

#if (CANNM_PN_FEATURE_ENABLED == STD_ON)
FUNC(void, CANNM_CODE) cannm_set_pni_cbv(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
		channel_internal->pdu_tx[channel_conf->pos_cbv] |= CANNM_CBV_PNI;
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
		channel_internal->spts_tx_msg[channel_conf->pos_cbv] |= CANNM_CBV_PNI;
#endif
	}
}
#endif

#if (CANNM_ACTIVE_WUP_BIT_FEATURE_ENABLED == STD_ON)
FUNC(void, CANNM_CODE) cannm_set_active_wk_cbv(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
		channel_internal->pdu_tx[channel_conf->pos_cbv] |= CANNM_CBV_ACTIVE_WAKEUP;
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
		channel_internal->spts_tx_msg[channel_conf->pos_cbv] |= CANNM_CBV_ACTIVE_WAKEUP;
#endif
	}
}

FUNC(void, CANNM_CODE) cannm_clr_active_wk_cbv(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	if (channel_conf->pos_cbv != CANNM_PDU_OFF) {
		channel_internal->pdu_tx[channel_conf->pos_cbv] =
			(uint8)(channel_internal->pdu_tx[channel_conf->pos_cbv] & (~(CANNM_CBV_ACTIVE_WAKEUP)));
#if (CANNM_USER_DATA_ENABLED == STD_ON) && (CANNM_COM_USER_DATA_SUPPORT == STD_ON)
		channel_internal->spts_tx_msg[channel_conf->pos_cbv] &= (uint8)(~(CANNM_CBV_ACTIVE_WAKEUP));
#endif
	}
}
#endif

FUNC(void, CANNM_CODE) cannm_switch_mode_state_proc(cannm_op_chnl_cate *channel_internal, nm_mode_type mode,
	nm_state_type state)
{
	if (NULL == channel_internal) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->mode = mode;
	channel_internal->state = state;
}

FUNC(void, CANNM_CODE) cannm_imdt_tx_proc(cannm_op_chnl_cate *channel_internal)
{
	if (NULL == channel_internal) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->left_msg_cyc_tm = 0u;
	channel_internal->imdt_tx_sd = 0u;
	channel_internal->imdt_en_mode = (boolean)TRUE;
}

FUNC(void, CANNM_CODE) cannm_pbs_to_rpt_msg_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal, boolean is_nw_req)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
#if (CANNM_RETRY_FIRST_MESSAGE_REQUEST == STD_ON)
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[channel_conf->id_net];

	cannm_retry_first_msg_flg[cannm_net_id] = (boolean)TRUE;
#endif
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_REPEAT_MESSAGE);
	if ((channel_conf->imdt_tx > 0U) && is_nw_req) {
		cannm_imdt_tx_proc(channel_internal);
	} else {
		channel_internal->left_msg_cyc_tm = channel_conf->msg_cys_ofst_tm + channel_conf->m_func_pid;
	}
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm + channel_conf->m_func_pid;
	channel_internal->left_tmot_tm = channel_conf->tm_out + channel_conf->m_func_pid;

	nm_mode_net_proc(channel_conf->id_net);
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_PREPARE_BUS_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_PREPARE_BUS_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
}

FUNC(void, CANNM_CODE) cannm_pbs_to_bs_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_BUS_SLEEP, NM_MODE_BUS_SLEEP);
	nm_mode_bs_proc(channel_conf->id_net);
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_PREPARE_BUS_SLEEP, NM_STATE_BUS_SLEEP);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_PREPARE_BUS_SLEEP, NM_STATE_BUS_SLEEP);
#endif
}

FUNC(void, CANNM_CODE) cannm_bs_to_rpt_msg_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal, boolean is_nw_req)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
#if (CANNM_RETRY_FIRST_MESSAGE_REQUEST == STD_ON)
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[channel_conf->id_net];

	cannm_retry_first_msg_flg[cannm_net_id] = (boolean)TRUE;
#endif
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_REPEAT_MESSAGE);
	if ((channel_conf->imdt_tx > 0U) && is_nw_req) {
		cannm_imdt_tx_proc(channel_internal);
	} else {
		channel_internal->left_msg_cyc_tm = channel_conf->msg_cys_ofst_tm + channel_conf->m_func_pid;
	}
	channel_internal->left_tmot_tm = channel_conf->tm_out + channel_conf->m_func_pid;
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm + channel_conf->m_func_pid;
	nm_mode_net_proc(channel_conf->id_net);
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_BUS_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_BUS_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
}

FUNC(void, CANNM_CODE) cannm_bs_to_bs_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	nm_start_net_ind(channel_conf->id_net);
	(void) channel_internal;
}

FUNC(void, CANNM_CODE) cannm_rpt_msg_to_rpt_msg_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->left_tmot_tm = channel_conf->tm_out;
}

FUNC(void, CANNM_CODE) cannm_rpt_msg_to_rdy_slp_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
#if (CANNM_RETRY_FIRST_MESSAGE_REQUEST == STD_ON)
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[channel_conf->id_net];

	cannm_retry_first_msg_flg[cannm_net_id] = (boolean)FALSE;
#endif
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_READY_SLEEP);
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
	cannm_clr_rpt_msg_req_cbv(channel_conf, channel_internal);
#endif
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_REPEAT_MESSAGE, NM_STATE_READY_SLEEP);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_REPEAT_MESSAGE, NM_STATE_READY_SLEEP);
#endif
}

FUNC(void, CANNM_CODE) cannm_rpt_msg_to_nor_opr_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_NORMAL_OPERATION);
#if (CANNM_NODE_DETECTION_ENABLED == STD_ON)
	cannm_clr_rpt_msg_req_cbv(channel_conf, channel_internal);
#endif
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_REPEAT_MESSAGE, NM_STATE_NORMAL_OPERATION);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_REPEAT_MESSAGE, NM_STATE_NORMAL_OPERATION);
#endif
}

#if ((CANNM_NODE_DETECTION_ENABLED == STD_ON) || (STD_OFF != CANNM_PN_HANDLE_MULTIPLE_NETWORK_REQUESTS))
FUNC(void, CANNM_CODE) cannm_nor_opr_to_rpt_msg_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_REPEAT_MESSAGE);
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm + channel_conf->m_func_pid;
	channel_internal->left_msg_cyc_tm = channel_conf->msg_cys_ofst_tm + channel_conf->m_func_pid;
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_NORMAL_OPERATION, NM_STATE_REPEAT_MESSAGE);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_NORMAL_OPERATION, NM_STATE_REPEAT_MESSAGE);
#endif
}
#endif

FUNC(void, CANNM_CODE) cannm_nor_opr_to_rdy_slp_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
#if (CANNM_RETRY_FIRST_MESSAGE_REQUEST == STD_ON)
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[channel_conf->id_net];

	cannm_retry_first_msg_flg[cannm_net_id] = (boolean)FALSE;
#endif
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_READY_SLEEP);
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_NORMAL_OPERATION, NM_STATE_READY_SLEEP);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
	(void) channel_conf;
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_NORMAL_OPERATION, NM_STATE_READY_SLEEP);
#endif
}

FUNC(void, CANNM_CODE) cannm_nor_opr_to_nor_opr_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->left_tmot_tm = channel_conf->tm_out;
}

FUNC(void, CANNM_CODE) cannm_rdy_slp_to_nor_opr_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_NORMAL_OPERATION);
	channel_internal->left_msg_cyc_tm = channel_conf->msg_cys_ofst_tm + channel_conf->m_func_pid;
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_NORMAL_OPERATION);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_NORMAL_OPERATION);
#endif
}

FUNC(void, CANNM_CODE) cannm_rdy_slp_to_pbs_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_PREPARE_BUS_SLEEP, NM_STATE_PREPARE_BUS_SLEEP);
	channel_internal->left_wait_bs_tm = channel_conf->wait_bs_tm;
	channel_internal->left_msg_tmot_tm = 0u;
	nm_mode_pbs_proc(channel_conf->id_net);

#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_PREPARE_BUS_SLEEP);
#endif

#if (CANNM_ACTIVE_WUP_BIT_FEATURE_ENABLED == STD_ON)
	cannm_clr_active_wk_cbv(channel_conf, channel_internal);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_PREPARE_BUS_SLEEP);
#endif
}

#if ((CANNM_NODE_DETECTION_ENABLED == STD_ON) || (STD_OFF != CANNM_PN_HANDLE_MULTIPLE_NETWORK_REQUESTS))

FUNC(void, CANNM_CODE) cannm_rdy_slp_to_rpt_msg_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_REPEAT_MESSAGE);
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm + channel_conf->m_func_pid;
	channel_internal->left_msg_cyc_tm = channel_conf->msg_cys_ofst_tm + channel_conf->m_func_pid;
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
}
#endif

FUNC(void, CANNM_CODE) cannm_net_mode_to_net_mode_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return;
	}
	channel_internal->left_tmot_tm = channel_conf->tm_out + channel_conf->m_func_pid;
}

#if (CANNM_PN_FEATURE_ENABLED == STD_ON)
FUNC(Std_ReturnType, CANNM_CODE) cannm_nor_rx_proc(const cannm_chnl_cate *channel_conf,
	boolean pni)
{
	if (NULL == channel_conf) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RX_NORMAL_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if (!channel_conf->pn_support) {
		return E_OK;
	}
	if ((channel_conf->all_msg_wk) && (!pni)) {
		return E_OK;
	}
	return E_NOT_OK;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_dscd_rx_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal, boolean pni)
{
	if (NULL == channel_conf) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RX_DISCARD_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if (NULL == channel_internal) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_RX_DISCARD_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if ((!channel_conf->all_msg_wk) && (!pni)) {
		return E_NOT_OK;
	}
	if (!channel_internal->filter_pdu) {
		return E_NOT_OK;
	}
	return E_OK;
}

FUNC(Std_ReturnType, CANNM_CODE) cannm_rx_proc(const cannm_chnl_cate *channel_conf,
	cannm_op_chnl_cate *channel_internal, boolean pni)
{
	if ((NULL == channel_conf) || (NULL == channel_internal)) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_MAINFUNCTION_CANNM_E_NULL_POINTER);
		return E_NOT_OK;
	}
	if (E_OK == cannm_nor_rx_proc(channel_conf, pni)) {
		return E_OK;
	}
	if (E_NOT_OK == cannm_dscd_rx_proc(channel_conf, channel_internal, pni)) {
		return E_NOT_OK;
	}
}
#endif

FUNC(boolean, CANNM_CODE) cannm_monitor_get_current_requested(uint8 channel)
{
	return cannm_internal.nm_tunnel[channel].requested;
}

FUNC(uint16, CANNM_CODE) cannm_get_canif_first_nm_msg_id(void)
{
	return canif_first_nm_msg_id;
}

FUNC(void, CANNM_CODE) cannm_nor_opr_to_rpt_msg_imdt_tx(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NO_INIT);
		return;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	if (channel_internal->state != NM_STATE_NORMAL_OPERATION) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_REPEAT_MESSAGE);
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm;
	if (channel_conf->imdt_tx > 0U) {
		cannm_imdt_tx_proc(channel_internal);
	}
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_NORMAL_OPERATION, NM_STATE_REPEAT_MESSAGE);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();

#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_NORMAL_OPERATION, NM_STATE_REPEAT_MESSAGE);
#endif
}

FUNC(void, CANNM_CODE) cannm_rpt_msg_to_rpt_msg_imdt_tx(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NO_INIT);
		return;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	if (channel_internal->state != NM_STATE_REPEAT_MESSAGE) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	channel_internal->left_tmot_tm = channel_conf->tm_out;
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm;
	if (channel_conf->imdt_tx > 0U) {
		cannm_imdt_tx_proc(channel_internal);
	}
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();
}

FUNC(void, CANNM_CODE) cannm_rdy_slp_to_rpt_msg_imdt_tx(const network_handle_type nm_id)
{
	if (CANNM_STATUS_UNINIT == cannm_internal.init_status) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_NO_INIT);
		return;
	}
	if (nm_id >= cannm_config_ptr->chnl_num_len) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	network_handle_type cannm_net_id = cannm_config_ptr->tunnel_trans[nm_id];
	uint8 channel_index = cannm_config_ptr->chnl_num[cannm_net_id];
	const cannm_chnl_cate *channel_conf = &cannm_config_ptr->nm_tunnel[channel_index];
	cannm_op_chnl_cate *channel_internal = &cannm_internal.nm_tunnel[channel_index];

	if (channel_internal->state != NM_STATE_READY_SLEEP) {
		CANNM_DET_REPORT(CANNM_CANNM_SERVICEID_GETSTATE_CANNM_E_INVALID_CHANNEL);
		return;
	}
	SchM_Enter_CANNM_EXCLUSIVE_AREA_0();
	cannm_switch_mode_state_proc(channel_internal, NM_MODE_NETWORK, NM_STATE_REPEAT_MESSAGE);
	channel_internal->left_rpt_msg_tm = channel_conf->rpt_msg_tm;
	if (channel_conf->imdt_tx > 0U) {
		cannm_imdt_tx_proc(channel_internal);
	}
#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg_bswm(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
	SchM_Exit_CANNM_EXCLUSIVE_AREA_0();

#if (CANNM_STATE_CHANGE_IND_ENABLED == STD_ON)
	nm_ntfy_state_chg(channel_conf->id_net, NM_STATE_READY_SLEEP, NM_STATE_REPEAT_MESSAGE);
#endif
}

#define CANNM_STOP_SEC_CODE
#include "cannm_memmap.h"
